#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import json
import sys
import ast
import importlib.util
import re
import math
from collections import defaultdict

app = Flask(__name__)
CORS(app)

# 支持的文件类型和对应的解析器
SUPPORTED_EXTENSIONS = {
    '.py': 'python',
    '.java': 'java',
    '.js': 'javascript',
    '.html': 'html',
    '.css': 'css',
    '.php': 'php',
    '.c': 'c',
    '.cpp': 'cpp',
    '.h': 'c',
    '.hpp': 'cpp',
    '.cs': 'csharp',
    '.go': 'go',
    '.rb': 'ruby',
    '.rs': 'rust',
    '.ts': 'typescript',
    '.xml': 'xml',
    '.json': 'json',
    '.md': 'markdown',
    '.sql': 'sql',
    '.sh': 'bash',
    '.yml': 'yaml',
    '.yaml': 'yaml',
}

# 设计模式定义和特征
DESIGN_PATTERNS = {
    'singleton': {
        'description': '单例模式确保一个类只有一个实例，并提供一个全局访问点。',
        'features': [
            r'private\s+static\s+\w+\s+instance',  # Java
            r'static\s+getInstance\(',  # Java
            r'private\s+constructor',  # TypeScript
            r'@staticmethod\s+def\s+get_instance',  # Python
            r'_instance\s*=\s*None',  # Python
        ]
    },
    'factory': {
        'description': '工厂模式定义一个创建对象的接口，让子类决定实例化哪一个类。',
        'features': [
            r'create\w+\s*\(',  # 通用
            r'factory\s+method',  # 注释
            r'abstract\s+\w+\s+create\w+',  # Java
            r'def\s+create_\w+',  # Python
        ]
    },
    'observer': {
        'description': '观察者模式定义对象间的一种一对多依赖关系，使得当一个对象状态改变时，所有依赖于它的对象都会得到通知并自动更新。',
        'features': [
            r'notify\w*\(',  # 通用
            r'observer\s+pattern',  # 注释
            r'addListener|addEventListener',  # JavaScript
            r'(add|remove)Observer',  # 通用
            r'update\s*\(\s*\w+\s*\)',  # 通用
        ]
    },
    'mvc': {
        'description': 'MVC模式将应用分为模型、视图和控制器三个部分。',
        'features': [
            r'class\s+\w+Model',  # 通用
            r'class\s+\w+View',  # 通用
            r'class\s+\w+Controller',  # 通用
            r'mvc\s+pattern',  # 注释
        ]
    },
}

class CodeAnalyzer:
    """代码分析器基类"""
    
    def __init__(self, project_path):
        self.project_path = project_path
        self.files = []
        self.analysis_results = {}
        self.dependency_graph = {}
        
    def scan_files(self):
        """扫描项目文件"""
        for root, _, files in os.walk(self.project_path):
            for file in files:
                file_path = os.path.join(root, file)
                _, ext = os.path.splitext(file)
                if ext.lower() in SUPPORTED_EXTENSIONS:
                    self.files.append(file_path)
        return self.files
    
    def analyze_file(self, file_path):
        """分析单个文件"""
        _, ext = os.path.splitext(file_path)
        language = SUPPORTED_EXTENSIONS.get(ext.lower())
        
        if not language:
            return {"error": f"Unsupported file type: {ext}"}
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                
            # 基本文件信息
            file_info = {
                "path": file_path,
                "language": language,
                "size": os.path.getsize(file_path),
                "lines": len(content.splitlines()),
                "content": content
            }
            
            # 提取注释
            file_info["comments"] = self.extract_comments(content, language)
            
            # 检测设计模式
            file_info["design_patterns"] = self.detect_design_patterns(content)
            
            # 计算代码复杂度
            file_info["complexity"] = self.calculate_complexity(content, language)
            
            # 根据不同语言调用不同的分析方法
            if language == 'python':
                file_info.update(self.analyze_python(content, file_path))
            elif language == 'javascript' or language == 'typescript':
                file_info.update(self.analyze_javascript(content, file_path))
            elif language == 'java':
                file_info.update(self.analyze_java(content, file_path))
            # 可以添加其他语言的分析方法
            
            return file_info
        except Exception as e:
            return {"error": str(e)}
    
    def extract_comments(self, content, language):
        """提取代码注释"""
        comments = []
        
        if language == 'python':
            # 单行注释
            single_line_comments = re.findall(r'#.*$', content, re.MULTILINE)
            comments.extend(single_line_comments)
            
            # 多行注释 (文档字符串)
            doc_strings = re.findall(r'"""(.*?)"""', content, re.DOTALL)
            comments.extend(doc_strings)
            doc_strings = re.findall(r"'''(.*?)'''", content, re.DOTALL)
            comments.extend(doc_strings)
            
        elif language in ['javascript', 'typescript', 'java', 'c', 'cpp', 'csharp']:
            # 单行注释
            single_line_comments = re.findall(r'//.*$', content, re.MULTILINE)
            comments.extend(single_line_comments)
            
            # 多行注释
            multi_line_comments = re.findall(r'/\*(.*?)\*/', content, re.DOTALL)
            comments.extend(multi_line_comments)
            
        return [comment.strip() for comment in comments if comment.strip()]
    
    def detect_design_patterns(self, content):
        """检测代码中的设计模式"""
        detected_patterns = []
        
        for pattern_name, pattern_info in DESIGN_PATTERNS.items():
            for feature in pattern_info['features']:
                if re.search(feature, content, re.IGNORECASE | re.MULTILINE):
                    detected_patterns.append({
                        'name': pattern_name,
                        'description': pattern_info['description']
                    })
                    break  # 找到一个特征就确认该模式存在
        
        return detected_patterns
    
    def calculate_complexity(self, content, language):
        """计算代码复杂度"""
        complexity = {
            "cyclomatic_complexity": None,
            "maintainability_index": None,
            "raw_metrics": None
        }
        
        # 简单的复杂度计算
        if language == 'python':
            try:
                # 计算条件语句和循环数量作为简单的复杂度指标
                conditions = len(re.findall(r'\bif\b|\belif\b|\belse\b|\bfor\b|\bwhile\b|\btry\b|\bexcept\b', content))
                functions = len(re.findall(r'\bdef\b', content))
                classes = len(re.findall(r'\bclass\b', content))
                
                # 简单的圈复杂度计算
                cc = 1 + conditions
                
                # 简单的可维护性指标计算 (基于代码行数、注释比例和复杂度)
                lines = len(content.splitlines())
                comments = len(self.extract_comments(content, language))
                comment_ratio = comments / max(lines, 1)
                mi = 100 - (lines / 100) - (cc / 10) + (comment_ratio * 20)
                
                complexity["cyclomatic_complexity"] = {
                    "average": cc,
                    "details": [
                        {
                            "name": "全文件",
                            "complexity": cc,
                            "rank": "A" if cc < 5 else ("B" if cc < 10 else "C")
                        }
                    ]
                }
                
                complexity["maintainability_index"] = mi
                
                complexity["raw_metrics"] = {
                    "loc": lines,
                    "lloc": lines - comments,
                    "sloc": lines,
                    "comments": comments,
                    "multi": 0,
                    "blank": content.count('\n\n')
                }
            except Exception as e:
                complexity["error"] = str(e)
        
        return complexity
    
    def analyze_python(self, content, file_path):
        """分析Python代码"""
        result = {
            "imports": [],
            "classes": [],
            "functions": [],
            "variables": []
        }
        
        try:
            tree = ast.parse(content)
            
            # 分析导入
            for node in ast.walk(tree):
                if isinstance(node, ast.Import):
                    for name in node.names:
                        result["imports"].append(name.name)
                        # 添加依赖关系
                        if file_path not in self.dependency_graph:
                            self.dependency_graph[file_path] = []
                        self.dependency_graph[file_path].append(name.name)
                elif isinstance(node, ast.ImportFrom):
                    module = node.module or ""
                    for name in node.names:
                        import_name = f"{module}.{name.name}"
                        result["imports"].append(import_name)
                        # 添加依赖关系
                        if file_path not in self.dependency_graph:
                            self.dependency_graph[file_path] = []
                        self.dependency_graph[file_path].append(import_name)
            
            # 直接分析顶层节点，避免重复计算
            for node in tree.body:
                # 分析类
                if isinstance(node, ast.ClassDef):
                    class_info = {
                        "name": node.name,
                        "methods": [],
                        "line_number": node.lineno,
                        "docstring": ast.get_docstring(node)
                    }
                    
                    # 获取类的方法
                    for item in node.body:
                        if isinstance(item, ast.FunctionDef):
                            method_info = {
                                "name": item.name,
                                "line_number": item.lineno,
                                "args": [arg.arg for arg in item.args.args if arg.arg != 'self'],
                                "docstring": ast.get_docstring(item)
                            }
                            class_info["methods"].append(method_info)
                    
                    result["classes"].append(class_info)
                
                # 分析函数
                elif isinstance(node, ast.FunctionDef):
                    func_info = {
                        "name": node.name,
                        "line_number": node.lineno,
                        "args": [arg.arg for arg in node.args.args],
                        "docstring": ast.get_docstring(node)
                    }
                    result["functions"].append(func_info)
                
                # 分析全局变量
                elif isinstance(node, ast.Assign) and all(isinstance(target, ast.Name) for target in node.targets):
                    for target in node.targets:
                        if isinstance(target, ast.Name):
                            var_info = {
                                "name": target.id,
                                "line_number": node.lineno
                            }
                            result["variables"].append(var_info)
        
        except SyntaxError as e:
            result["syntax_error"] = str(e)
        
        return result
    
    def analyze_javascript(self, content, file_path):
        """分析JavaScript/TypeScript代码"""
        result = {
            "imports": [],
            "classes": [],
            "functions": [],
            "variables": []
        }
        
        # 提取导入语句
        import_patterns = [
            r'import\s+{([^}]+)}\s+from\s+[\'"]([^\'"]+)[\'"]',  # import { x } from 'y'
            r'import\s+(\w+)\s+from\s+[\'"]([^\'"]+)[\'"]',      # import x from 'y'
            r'import\s+[\'"]([^\'"]+)[\'"]',                     # import 'x'
            r'require\([\'"]([^\'"]+)[\'"]\)'                    # require('x')
        ]
        
        for pattern in import_patterns:
            for match in re.finditer(pattern, content):
                if len(match.groups()) == 2:
                    imports = match.group(1).split(',')
                    module = match.group(2)
                    for imp in imports:
                        imp = imp.strip()
                        if imp:
                            result["imports"].append(f"{module}.{imp}")
                            if file_path not in self.dependency_graph:
                                self.dependency_graph[file_path] = []
                            self.dependency_graph[file_path].append(f"{module}.{imp}")
                elif len(match.groups()) == 1:
                    module = match.group(1)
                    result["imports"].append(module)
                    if file_path not in self.dependency_graph:
                        self.dependency_graph[file_path] = []
                    self.dependency_graph[file_path].append(module)
        
        # 提取类 - 修复React类组件识别
        class_patterns = [
            r'class\s+(\w+)(?:\s+extends\s+(\w+))?\s*{([^}]+)}',  # 标准类语法
            r'class\s+(\w+)(?:\s+extends\s+[\w.]+)?\s*{([^}]+)}',  # React组件类语法
        ]
        
        for pattern in class_patterns:
            for match in re.finditer(pattern, content, re.DOTALL):
                class_name = match.group(1)
                class_body = match.groups()[-1]  # 最后一个组是类体
                
                class_info = {
                    "name": class_name,
                    "methods": [],
                    "line_number": content[:match.start()].count('\n') + 1
                }
                
                if len(match.groups()) > 2:
                    parent_class = match.group(2)
                    if parent_class:
                        class_info["extends"] = parent_class
                
                # 提取方法
                method_pattern = r'(?:async\s+)?(?:static\s+)?(\w+)\s*\(([^)]*)\)'
                for method_match in re.finditer(method_pattern, class_body):
                    method_name = method_match.group(1)
                    method_args = method_match.group(2).split(',')
                    
                    method_info = {
                        "name": method_name,
                        "line_number": content[:match.start() + method_match.start()].count('\n') + 1,
                        "args": [arg.strip() for arg in method_args if arg.strip()]
                    }
                    
                    class_info["methods"].append(method_info)
                
                result["classes"].append(class_info)
        
        # 提取函数
        function_patterns = [
            r'function\s+(\w+)\s*\(([^)]*)\)',  # function name(args)
            r'const\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*=>'  # const name = (args) =>
        ]
        
        for pattern in function_patterns:
            for match in re.finditer(pattern, content):
                func_name = match.group(1)
                func_args = []
                if len(match.groups()) > 1:
                    func_args = [arg.strip() for arg in match.group(2).split(',') if arg.strip()]
                
                func_info = {
                    "name": func_name,
                    "line_number": content[:match.start()].count('\n') + 1,
                    "args": func_args
                }
                
                result["functions"].append(func_info)
        
        # 提取变量
        var_patterns = [
            r'(?:var|let|const)\s+(\w+)\s*=',  # var/let/const name =
        ]
        
        for pattern in var_patterns:
            for match in re.finditer(pattern, content):
                var_name = match.group(1)
                
                var_info = {
                    "name": var_name,
                    "line_number": content[:match.start()].count('\n') + 1
                }
                
                result["variables"].append(var_info)
        
        return result
    
    def analyze_java(self, content, file_path):
        """分析Java代码"""
        result = {
            "imports": [],
            "classes": [],
            "methods": [],
            "fields": []
        }
        
        # 提取导入语句
        import_pattern = r'import\s+([\w.]+)(?:\s*;\s*|$)'
        for match in re.finditer(import_pattern, content):
            import_name = match.group(1)
            result["imports"].append(import_name)
            if file_path not in self.dependency_graph:
                self.dependency_graph[file_path] = []
            self.dependency_graph[file_path].append(import_name)
        
        # 提取包声明
        package_pattern = r'package\s+([\w.]+)(?:\s*;\s*|$)'
        package_match = re.search(package_pattern, content)
        if package_match:
            result["package"] = package_match.group(1)
        
        # 提取类
        class_pattern = r'(?:public|private|protected)?\s*(?:abstract|final)?\s*class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?\s*{([^}]+)}'
        for match in re.finditer(class_pattern, content, re.DOTALL):
            class_name = match.group(1)
            parent_class = match.group(2)
            interfaces = match.group(3)
            class_body = match.group(4)
            
            class_info = {
                "name": class_name,
                "methods": [],
                "fields": [],
                "line_number": content[:match.start()].count('\n') + 1
            }
            
            if parent_class:
                class_info["extends"] = parent_class
            
            if interfaces:
                class_info["implements"] = [i.strip() for i in interfaces.split(',')]
            
            # 提取方法
            method_pattern = r'(?:public|private|protected)?\s*(?:static|final|abstract)?\s*(?:<[^>]+>\s*)?(\w+)\s+(\w+)\s*\(([^)]*)\)'
            for method_match in re.finditer(method_pattern, class_body):
                return_type = method_match.group(1)
                method_name = method_match.group(2)
                method_args = method_match.group(3).split(',')
                
                method_info = {
                    "name": method_name,
                    "return_type": return_type,
                    "line_number": content[:match.start() + method_match.start()].count('\n') + 1,
                    "args": []
                }
                
                for arg in method_args:
                    arg = arg.strip()
                    if arg:
                        arg_parts = arg.split()
                        if len(arg_parts) >= 2:
                            method_info["args"].append({
                                "type": arg_parts[0],
                                "name": arg_parts[1]
                            })
                
                class_info["methods"].append(method_info)
            
            # 提取字段
            field_pattern = r'(?:public|private|protected)?\s*(?:static|final)?\s*(\w+)\s+(\w+)\s*(?:=\s*[^;]+)?;'
            for field_match in re.finditer(field_pattern, class_body):
                field_type = field_match.group(1)
                field_name = field_match.group(2)
                
                field_info = {
                    "name": field_name,
                    "type": field_type,
                    "line_number": content[:match.start() + field_match.start()].count('\n') + 1
                }
                
                class_info["fields"].append(field_info)
            
            result["classes"].append(class_info)
        
        return result
    
    def analyze_project_structure(self):
        """分析项目结构"""
        structure = {
            "directories": defaultdict(list),
            "file_types": defaultdict(int),
            "language_distribution": defaultdict(int)
        }
        
        for file_path in self.files:
            rel_path = os.path.relpath(file_path, self.project_path)
            dir_name = os.path.dirname(rel_path)
            
            structure["directories"][dir_name].append(os.path.basename(file_path))
            
            _, ext = os.path.splitext(file_path)
            structure["file_types"][ext.lower()] += 1
            
            language = SUPPORTED_EXTENSIONS.get(ext.lower())
            if language:
                structure["language_distribution"][language] += 1
        
        return structure
    
    def analyze_dependencies(self):
        """分析项目依赖关系"""
        # 依赖关系已在分析各个文件时添加到dependency_graph
        
        # 计算每个文件的依赖度
        dependency_metrics = {}
        for file_path, dependencies in self.dependency_graph.items():
            if os.path.isfile(file_path):  # 只分析文件节点
                rel_path = os.path.relpath(file_path, self.project_path)
                in_degree = 0  # 被依赖数
                out_degree = len(dependencies)  # 依赖其他数
                
                # 计算被依赖数
                for other_file, other_deps in self.dependency_graph.items():
                    if file_path in other_deps:
                        in_degree += 1
                
                dependency_metrics[rel_path] = {
                    "in_degree": in_degree,
                    "out_degree": out_degree,
                    "total_degree": in_degree + out_degree
                }
        
        # 找出核心组件（被依赖最多的文件）
        core_components = sorted(
            dependency_metrics.items(),
            key=lambda x: x[1]["in_degree"],
            reverse=True
        )[:10]
        
        return {
            "metrics": dependency_metrics,
            "core_components": core_components
        }
    
    def analyze_code_quality(self):
        """分析代码质量"""
        quality_metrics = {
            "average_complexity": 0,
            "maintainability": 0,
            "code_to_comment_ratio": 0,
            "files_with_high_complexity": [],
            "files_with_low_maintainability": []
        }
        
        total_complexity = 0
        total_maintainability = 0
        total_code_lines = 0
        total_comment_lines = 0
        files_with_metrics = 0
        
        for file_path, file_info in self.analysis_results.items():
            if "complexity" in file_info and file_info["complexity"]["cyclomatic_complexity"]:
                complexity = file_info["complexity"]["cyclomatic_complexity"]["average"]
                total_complexity += complexity
                
                if complexity > 10:  # 高复杂度阈值
                    quality_metrics["files_with_high_complexity"].append({
                        "file": file_path,
                        "complexity": complexity
                    })
            
            if "complexity" in file_info and file_info["complexity"]["maintainability_index"]:
                maintainability = file_info["complexity"]["maintainability_index"]
                total_maintainability += maintainability
                
                if maintainability < 65:  # 低可维护性阈值
                    quality_metrics["files_with_low_maintainability"].append({
                        "file": file_path,
                        "maintainability": maintainability
                    })
            
            if "complexity" in file_info and file_info["complexity"]["raw_metrics"]:
                raw = file_info["complexity"]["raw_metrics"]
                total_code_lines += raw["lloc"]
                total_comment_lines += raw["comments"]
            
            files_with_metrics += 1
        
        if files_with_metrics > 0:
            quality_metrics["average_complexity"] = total_complexity / files_with_metrics
            quality_metrics["maintainability"] = total_maintainability / files_with_metrics
        
        if total_code_lines > 0:
            quality_metrics["code_to_comment_ratio"] = total_comment_lines / total_code_lines
        
        return quality_metrics
    
    def analyze_project(self):
        """分析整个项目"""
        self.scan_files()
        
        for file_path in self.files:
            rel_path = os.path.relpath(file_path, self.project_path)
            self.analysis_results[rel_path] = self.analyze_file(file_path)
        
        # 项目结构分析
        project_structure = self.analyze_project_structure()
        
        # 依赖关系分析
        dependencies = self.analyze_dependencies()
        
        # 代码质量分析
        code_quality = self.analyze_code_quality()
        
        # 项目概览
        overview = {
            "total_files": len(self.files),
            "languages": project_structure["language_distribution"],
            "file_types": project_structure["file_types"],
            "largest_files": [],
            "most_complex_files": [],
            "core_components": dependencies["core_components"],
            "code_quality": code_quality
        }
        
        # 按大小排序文件
        sorted_by_size = sorted(
            self.analysis_results.items(), 
            key=lambda x: x[1].get("size", 0), 
            reverse=True
        )
        overview["largest_files"] = [path for path, _ in sorted_by_size[:10]]
        
        # 按复杂度排序文件
        sorted_by_complexity = sorted(
            [(path, info) for path, info in self.analysis_results.items() 
             if "complexity" in info and info["complexity"]["cyclomatic_complexity"]],
            key=lambda x: x[1]["complexity"]["cyclomatic_complexity"]["average"],
            reverse=True
        )
        overview["most_complex_files"] = [path for path, _ in sorted_by_complexity[:10]]
        
        return {
            "overview": overview,
            "structure": project_structure,
            "dependencies": dependencies,
            "files": self.analysis_results
        }

class ReportGenerator:
    """报告生成器"""
    
    def __init__(self, analysis_results):
        self.analysis_results = analysis_results
        
    def generate_html_report(self):
        """生成HTML格式的报告"""
        overview = self.analysis_results["overview"]
        structure = self.analysis_results["structure"]
        dependencies = self.analysis_results["dependencies"]
        files = self.analysis_results["files"]
        
        # 使用format方法而不是f-string，避免KeyError
        html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>代码解读报告</title>
            <style>
                body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; }}
                h1, h2, h3, h4 {{ color: #333; }}
                .section {{ margin-bottom: 30px; }}
                .file-list {{ list-style-type: none; padding: 0; }}
                .file-item {{ padding: 10px; margin: 5px 0; background-color: #f5f5f5; border-radius: 5px; }}
                .stats {{ display: flex; flex-wrap: wrap; }}
                .stat-item {{ margin-right: 20px; margin-bottom: 10px; }}
                pre {{ background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto; }}
                .highlight {{ background-color: #f8f8f8; }}
                table {{ border-collapse: collapse; width: 100%; margin-bottom: 20px; }}
                th, td {{ text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }}
                th {{ background-color: #f2f2f2; }}
                .quality-good {{ color: green; }}
                .quality-medium {{ color: orange; }}
                .quality-bad {{ color: red; }}
                .chart {{ width: 100%; height: 300px; margin-bottom: 20px; }}
            </style>
        </head>
        <body>
            <h1>代码解读报告</h1>
            
            <div class="section">
                <h2>项目概览</h2>
                <div class="stats">
                    <div class="stat-item">
                        <h3>文件总数</h3>
                        <p>{total_files}</p>
                    </div>
                    <div class="stat-item">
                        <h3>平均复杂度</h3>
                        <p class="{complexity_class}">{avg_complexity:.2f}</p>
                    </div>
                    <div class="stat-item">
                        <h3>可维护性指标</h3>
                        <p class="{maintainability_class}">{maintainability:.2f}</p>
                    </div>
                    <div class="stat-item">
                        <h3>注释比例</h3>
                        <p>{comment_ratio:.2%}</p>
                    </div>
                </div>
                
                <h3>语言分布</h3>
                <table>
                    <tr>
                        <th>语言</th>
                        <th>文件数</th>
                    </tr>
                    {language_rows}
                </table>
                
                <h3>核心组件</h3>
                <p>被其他组件依赖最多的文件：</p>
                <table>
                    <tr>
                        <th>文件</th>
                        <th>被依赖数</th>
                    </tr>
                    {core_component_rows}
                </table>
                
                <h3>最复杂文件</h3>
                <table>
                    <tr>
                        <th>文件</th>
                        <th>复杂度</th>
                    </tr>
                    {complex_file_rows}
                </table>
                
                <h3>最大文件</h3>
                <ul class="file-list">
                    {largest_files}
                </ul>
            </div>
            
            <div class="section">
                <h2>项目结构</h2>
                <h3>目录结构</h3>
                <ul>
                    {directory_structure}
                </ul>
            </div>
            
            <div class="section">
                <h2>设计模式检测</h2>
                <table>
                    <tr>
                        <th>文件</th>
                        <th>检测到的模式</th>
                        <th>描述</th>
                    </tr>
                    {design_pattern_rows}
                </table>
            </div>
            
            <div class="section">
                <h2>代码质量分析</h2>
                <h3>复杂度过高的文件</h3>
                <table>
                    <tr>
                        <th>文件</th>
                        <th>复杂度</th>
                    </tr>
                    {high_complexity_rows}
                </table>
                
                <h3>可维护性较低的文件</h3>
                <table>
                    <tr>
                        <th>文件</th>
                        <th>可维护性指标</th>
                    </tr>
                    {low_maintainability_rows}
                </table>
            </div>
            
            <div class="section">
                <h2>文件分析</h2>
                {file_analysis}
            </div>
        </body>
        </html>
        """.format(
            total_files=overview["total_files"],
            avg_complexity=overview["code_quality"]["average_complexity"],
            complexity_class=self._get_complexity_class(overview["code_quality"]["average_complexity"]),
            maintainability=overview["code_quality"]["maintainability"],
            maintainability_class=self._get_maintainability_class(overview["code_quality"]["maintainability"]),
            comment_ratio=overview["code_quality"]["code_to_comment_ratio"],
            language_rows="".join([
                f"<tr><td>{lang}</td><td>{count}</td></tr>"
                for lang, count in overview["languages"].items()
            ]),
            core_component_rows="".join([
                f"<tr><td>{file}</td><td>{metrics['in_degree']}</td></tr>"
                for file, metrics in overview["core_components"]
            ]) if overview["core_components"] else "<tr><td colspan='2'>无核心组件</td></tr>",
            complex_file_rows="".join([
                f"<tr><td>{file}</td><td class='{self._get_complexity_class(files[file]['complexity']['cyclomatic_complexity']['average'])}'>{files[file]['complexity']['cyclomatic_complexity']['average']:.2f}</td></tr>"
                for file in overview["most_complex_files"]
                if file in files and "complexity" in files[file] and files[file]["complexity"]["cyclomatic_complexity"]
            ]) if overview["most_complex_files"] else "<tr><td colspan='2'>无复杂文件</td></tr>",
            largest_files="".join([
                f"<li class='file-item'>{file} ({files[file]['size']} 字节)</li>"
                for file in overview["largest_files"]
                if file in files
            ]) if overview["largest_files"] else "<li class='file-item'>无大文件</li>",
            directory_structure="".join([
                f"""
                <li>
                    <strong>{dir_name or '根目录'}</strong>
                    <ul>
                        {"".join([f"<li>{file}</li>" for file in files])}
                    </ul>
                </li>
                """
                for dir_name, files in structure["directories"].items()
            ]),
            design_pattern_rows="".join([
                f"""
                <tr>
                    <td>{file}</td>
                    <td>{pattern['name']}</td>
                    <td>{pattern['description']}</td>
                </tr>
                """
                for file, info in files.items()
                if "design_patterns" in info
                for pattern in info["design_patterns"]
            ]) if any("design_patterns" in info and info["design_patterns"] for info in files.values()) else "<tr><td colspan='3'>未检测到设计模式</td></tr>",
            high_complexity_rows="".join([
                f"""
                <tr>
                    <td>{item['file']}</td>
                    <td class='quality-bad'>{item['complexity']:.2f}</td>
                </tr>
                """
                for item in overview["code_quality"]["files_with_high_complexity"]
            ]) if overview["code_quality"]["files_with_high_complexity"] else "<tr><td colspan='2'>无高复杂度文件</td></tr>",
            low_maintainability_rows="".join([
                f"""
                <tr>
                    <td>{item['file']}</td>
                    <td class='quality-bad'>{item['maintainability']:.2f}</td>
                </tr>
                """
                for item in overview["code_quality"]["files_with_low_maintainability"]
            ]) if overview["code_quality"]["files_with_low_maintainability"] else "<tr><td colspan='2'>无低可维护性文件</td></tr>",
            file_analysis="".join([
                self._generate_file_section(path, info)
                for path, info in files.items()
            ])
        )
        
        return html
    
    def _get_complexity_class(self, complexity):
        """根据复杂度返回CSS类"""
        if complexity < 5:
            return "quality-good"
        elif complexity < 10:
            return "quality-medium"
        else:
            return "quality-bad"
    
    def _get_maintainability_class(self, maintainability):
        """根据可维护性指标返回CSS类"""
        if maintainability > 80:
            return "quality-good"
        elif maintainability > 65:
            return "quality-medium"
        else:
            return "quality-bad"
    
    def _generate_file_section(self, path, info):
        """生成单个文件的分析部分"""
        if "error" in info:
            return f"""
            <div class="file-section">
                <h3>{path}</h3>
                <p>Error: {info["error"]}</p>
            </div>
            """
        
        # 复杂度信息
        complexity_html = ""
        if "complexity" in info and info["complexity"]["cyclomatic_complexity"]:
            complexity = info["complexity"]["cyclomatic_complexity"]["average"]
            complexity_html = f"""
            <div class="stat-item">
                <p>复杂度: <span class="{self._get_complexity_class(complexity)}">{complexity:.2f}</span></p>
            </div>
            """
        
        maintainability_html = ""
        if "complexity" in info and info["complexity"]["maintainability_index"]:
            maintainability = info["complexity"]["maintainability_index"]
            maintainability_html = f"""
            <div class="stat-item">
                <p>可维护性: <span class="{self._get_maintainability_class(maintainability)}">{maintainability:.2f}</span></p>
            </div>
            """
        
        # 设计模式信息
        design_patterns_html = ""
        if "design_patterns" in info and info["design_patterns"]:
            design_patterns_html = """
            <h4>检测到的设计模式</h4>
            <ul>
                {patterns}
            </ul>
            """.format(
                patterns="".join([
                    f"<li><strong>{pattern['name']}</strong>: {pattern['description']}</li>"
                    for pattern in info["design_patterns"]
                ])
            )
        
        # 类和函数信息
        classes_html = ""
        if "classes" in info and info["classes"]:
            classes_html = """
            <h4>类</h4>
            <table>
                <tr>
                    <th>名称</th>
                    <th>行号</th>
                    <th>方法数</th>
                    <th>文档</th>
                </tr>
                {rows}
            </table>
            """.format(
                rows="".join([
                    f"""
                    <tr>
                        <td>{cls["name"]}</td>
                        <td>{cls["line_number"]}</td>
                        <td>{len(cls["methods"])}</td>
                        <td>{cls.get("docstring", "")}</td>
                    </tr>
                    """
                    for cls in info["classes"]
                ])
            )
        
        functions_html = ""
        if "functions" in info and info["functions"]:
            functions_html = """
            <h4>函数</h4>
            <table>
                <tr>
                    <th>名称</th>
                    <th>行号</th>
                    <th>参数</th>
                    <th>文档</th>
                </tr>
                {rows}
            </table>
            """.format(
                rows="".join([
                    f"""
                    <tr>
                        <td>{func["name"]}</td>
                        <td>{func["line_number"]}</td>
                        <td>{', '.join(func["args"])}</td>
                        <td>{func.get("docstring", "")}</td>
                    </tr>
                    """
                    for func in info["functions"]
                ])
            )
        
        imports_html = ""
        if "imports" in info and info["imports"]:
            imports_html = """
            <h4>导入</h4>
            <ul>
                {items}
            </ul>
            """.format(
                items="".join([
                    f"<li>{imp}</li>"
                    for imp in info["imports"]
                ])
            )
        
        comments_html = ""
        if "comments" in info and info["comments"]:
            comments_html = """
            <h4>注释</h4>
            <ul>
                {items}
            </ul>
            """.format(
                items="".join([
                    f"<li>{comment}</li>"
                    for comment in info["comments"][:5]  # 只显示前5条注释
                ]) + (f"<li>... 共{len(info['comments'])}条注释</li>" if len(info["comments"]) > 5 else "")
            )
        
        return f"""
        <div class="file-section">
            <h3>{path}</h3>
            <div class="stats">
                <div class="stat-item">
                    <p>语言: {info.get("language", "未知")}</p>
                </div>
                <div class="stat-item">
                    <p>大小: {info.get("size", 0)} 字节</p>
                </div>
                <div class="stat-item">
                    <p>行数: {info.get("lines", 0)}</p>
                </div>
                {complexity_html}
                {maintainability_html}
            </div>
            
            {design_patterns_html}
            {imports_html}
            {classes_html}
            {functions_html}
            {comments_html}
            
            <h4>代码</h4>
            <pre><code>{info.get("content", "")[:500]}... (截断)</code></pre>
        </div>
        """
    
    def generate_markdown_report(self):
        """生成Markdown格式的报告"""
        overview = self.analysis_results["overview"]
        structure = self.analysis_results["structure"]
        dependencies = self.analysis_results["dependencies"]
        files = self.analysis_results["files"]
        
        md = """# 代码解读报告

## 项目概览

- 文件总数: {total_files}
- 平均复杂度: {avg_complexity:.2f}
- 可维护性指标: {maintainability:.2f}
- 注释比例: {comment_ratio:.2%}

### 语言分布

| 语言 | 文件数 |
|------|--------|
{language_rows}

### 核心组件

被其他组件依赖最多的文件：

| 文件 | 被依赖数 |
|------|----------|
{core_component_rows}

### 最复杂文件

| 文件 | 复杂度 |
|------|--------|
{complex_file_rows}

### 最大文件

{largest_files}

## 项目结构

### 目录结构

{directory_structure}

## 设计模式检测

| 文件 | 检测到的模式 | 描述 |
|------|--------------|------|
{design_pattern_rows}

## 代码质量分析

### 复杂度过高的文件

| 文件 | 复杂度 |
|------|--------|
{high_complexity_rows}

### 可维护性较低的文件

| 文件 | 可维护性指标 |
|------|--------------|
{low_maintainability_rows}

## 文件分析

{file_analysis}
""".format(
            total_files=overview["total_files"],
            avg_complexity=overview["code_quality"]["average_complexity"],
            maintainability=overview["code_quality"]["maintainability"],
            comment_ratio=overview["code_quality"]["code_to_comment_ratio"],
            language_rows="\n".join([
                f"| {lang} | {count} |"
                for lang, count in overview["languages"].items()
            ]),
            core_component_rows="\n".join([
                f"| {file} | {metrics['in_degree']} |"
                for file, metrics in overview["core_components"]
            ]) if overview["core_components"] else "| 无核心组件 | - |",
            complex_file_rows="\n".join([
                f"| {file} | {files[file]['complexity']['cyclomatic_complexity']['average']:.2f} |"
                for file in overview["most_complex_files"]
                if file in files and "complexity" in files[file] and files[file]["complexity"]["cyclomatic_complexity"]
            ]) if overview["most_complex_files"] else "| 无复杂文件 | - |",
            largest_files="\n".join([
                f"- {file} ({files[file]['size']} 字节)"
                for file in overview["largest_files"]
                if file in files
            ]) if overview["largest_files"] else "- 无大文件",
            directory_structure="\n".join([
                f"- **{dir_name or '根目录'}**\n" + "\n".join([f"  - {file}" for file in files])
                for dir_name, files in structure["directories"].items()
            ]),
            design_pattern_rows="\n".join([
                f"| {file} | {pattern['name']} | {pattern['description']} |"
                for file, info in files.items()
                if "design_patterns" in info
                for pattern in info["design_patterns"]
            ]) if any("design_patterns" in info and info["design_patterns"] for info in files.values()) else "| - | 未检测到设计模式 | - |",
            high_complexity_rows="\n".join([
                f"| {item['file']} | {item['complexity']:.2f} |"
                for item in overview["code_quality"]["files_with_high_complexity"]
            ]) if overview["code_quality"]["files_with_high_complexity"] else "| 无高复杂度文件 | - |",
            low_maintainability_rows="\n".join([
                f"| {item['file']} | {item['maintainability']:.2f} |"
                for item in overview["code_quality"]["files_with_low_maintainability"]
            ]) if overview["code_quality"]["files_with_low_maintainability"] else "| 无低可维护性文件 | - |",
            file_analysis="\n\n".join([
                self._generate_file_section_md(path, info)
                for path, info in files.items()
            ])
        )
        
        return md
    
    def _generate_file_section_md(self, path, info):
        """生成单个文件的Markdown分析部分"""
        if "error" in info:
            return f"""### {path}

Error: {info["error"]}"""
        
        # 复杂度信息
        complexity_md = ""
        if "complexity" in info and info["complexity"]["cyclomatic_complexity"]:
            complexity = info["complexity"]["cyclomatic_complexity"]["average"]
            complexity_md = f"- 复杂度: {complexity:.2f}"
        
        maintainability_md = ""
        if "complexity" in info and info["complexity"]["maintainability_index"]:
            maintainability = info["complexity"]["maintainability_index"]
            maintainability_md = f"- 可维护性: {maintainability:.2f}"
        
        # 设计模式信息
        design_patterns_md = ""
        if "design_patterns" in info and info["design_patterns"]:
            design_patterns_md = """#### 检测到的设计模式

{patterns}
""".format(
                patterns="\n".join([
                    f"- **{pattern['name']}**: {pattern['description']}"
                    for pattern in info["design_patterns"]
                ])
            )
        
        # 类和函数信息
        classes_md = ""
        if "classes" in info and info["classes"]:
            classes_md = """#### 类

| 名称 | 行号 | 方法数 | 文档 |
|------|------|--------|------|
{rows}
""".format(
                rows="\n".join([
                    f"| {cls['name']} | {cls['line_number']} | {len(cls['methods'])} | {cls.get('docstring', '')} |"
                    for cls in info["classes"]
                ])
            )
        
        functions_md = ""
        if "functions" in info and info["functions"]:
            functions_md = """#### 函数

| 名称 | 行号 | 参数 | 文档 |
|------|------|------|------|
{rows}
""".format(
                rows="\n".join([
                    f"| {func['name']} | {func['line_number']} | {', '.join(func['args'])} | {func.get('docstring', '')} |"
                    for func in info["functions"]
                ])
            )
        
        imports_md = ""
        if "imports" in info and info["imports"]:
            imports_md = """#### 导入

{items}
""".format(
                items="\n".join([
                    f"- {imp}"
                    for imp in info["imports"]
                ])
            )
        
        comments_md = ""
        if "comments" in info and info["comments"]:
            comments_md = """#### 注释

{items}
""".format(
                items="\n".join([
                    f"- {comment}"
                    for comment in info["comments"][:5]  # 只显示前5条注释
                ]) + (f"\n- ... 共{len(info['comments'])}条注释" if len(info["comments"]) > 5 else "")
            )
        
        return f"""### {path}

- 语言: {info.get("language", "未知")}
- 大小: {info.get("size", 0)} 字节
- 行数: {info.get("lines", 0)}
{complexity_md}
{maintainability_md}

{design_patterns_md}
{imports_md}
{classes_md}
{functions_md}
{comments_md}

#### 代码片段

```{info.get("language", "")}
{info.get("content", "")[:500]}... (截断)
```
"""

@app.route('/api/analyze', methods=['POST'])
def analyze_code():
    """分析上传的代码"""
    if 'file' not in request.files:
        return jsonify({"error": "No file part"}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({"error": "No selected file"}), 400
    
    # 创建临时目录保存上传的文件
    import tempfile
    import shutil
    import zipfile
    
    temp_dir = tempfile.mkdtemp()
    try:
        # 保存上传的文件
        file_path = os.path.join(temp_dir, file.filename)
        file.save(file_path)
        
        # 如果是zip文件，解压
        extract_dir = os.path.join(temp_dir, "extracted")
        os.makedirs(extract_dir, exist_ok=True)
        
        if file.filename.endswith('.zip'):
            with zipfile.ZipFile(file_path, 'r') as zip_ref:
                zip_ref.extractall(extract_dir)
            project_path = extract_dir
        else:
            # 单个文件
            shutil.copy(file_path, os.path.join(extract_dir, os.path.basename(file_path)))
            project_path = extract_dir
        
        # 分析代码
        analyzer = CodeAnalyzer(project_path)
        analysis_results = analyzer.analyze_project()
        
        # 生成报告
        report_generator = ReportGenerator(analysis_results)
        html_report = report_generator.generate_html_report()
        markdown_report = report_generator.generate_markdown_report()
        
        # 保存报告
        html_path = os.path.join(temp_dir, "report.html")
        with open(html_path, 'w', encoding='utf-8') as f:
            f.write(html_report)
            
        md_path = os.path.join(temp_dir, "report.md")
        with open(md_path, 'w', encoding='utf-8') as f:
            f.write(markdown_report)
        
        return jsonify({
            "success": True,
            "html_report": html_report,
            "markdown_report": markdown_report,
            "analysis_results": analysis_results
        })
    
    except Exception as e:
        return jsonify({"error": str(e)}), 500
    
    finally:
        # 清理临时目录
        shutil.rmtree(temp_dir)

@app.route('/api/health', methods=['GET'])
def health_check():
    """健康检查接口"""
    return jsonify({"status": "ok"})

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
